package com.yufubao.service.service.management.authorization.impl;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yufubao.framework.enums.CommonExceptionEnum;
import com.yufubao.framework.exception.BaseException;
import com.yufubao.framework.result.PageUtils;
import com.yufubao.framework.util.CopyBean;
import com.yufubao.framework.util.MyCollUtil;
import com.yufubao.framework.util.page.Query;
import com.yufubao.model.pojo.management.authorization.ManagerEntity;
import com.yufubao.model.pojo.management.authorization.ManagerRoleEntity;
import com.yufubao.model.pojo.management.authorization.RoleEntity;
import com.yufubao.model.vo.management.authorization.ManagerAddVo;
import com.yufubao.model.vo.management.authorization.ManagerVo;
import com.yufubao.model.vo.management.sys.SelectRoleVO;
import com.yufubao.model.vo.management.sys.UpdateManagerRoleVO;
import com.yufubao.service.mapper.management.authorization.ManagerDao;
import com.yufubao.service.service.management.authorization.ManagerRoleService;
import com.yufubao.service.service.management.authorization.ManagerService;
import com.yufubao.service.service.management.authorization.RoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.yufubao.framework.constant.GlobalPattern.PWD;
import static com.yufubao.framework.constant.ManagerStatus.*;


@Service("managerService")
@Slf4j
public class ManagerServiceImpl extends ServiceImpl<ManagerDao, ManagerEntity> implements ManagerService {

    @Autowired
    private ManagerRoleService managerRoleService;

    @Autowired
    private RoleService roleService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        //人员名称/手机号
        String key = (String) params.get("key");
        //状态
        String status = (String) params.get("status");

        LambdaQueryWrapper<ManagerEntity> wrapper = Wrappers.<ManagerEntity>lambdaQuery()
                .like(StrUtil.isNotBlank(key), ManagerEntity::getRealName, key)
                .or().eq(StrUtil.isNotBlank(key), ManagerEntity::getPhone, key);

        if (StrUtil.isNotBlank(status)) {
            switch (status) {
                case OPEN:
                    wrapper.and(wq -> wq.eq(ManagerEntity::getStatus, OPEN));
                    break;
                case STOP:
                    wrapper.and(wq -> wq.eq(ManagerEntity::getStatus, STOP));
                    break;
                default:
                    break;
            }
        }
        long managerId = StpUtil.getLoginIdAsLong();
        //admin查询所有
        if (!Objects.equals(managerId, ADMIN)) {
            wrapper.eq(ManagerEntity::getHigherId, managerId);
        }

        IPage<ManagerEntity> page = this.page(
                new Query<ManagerEntity>().getPage(params),
                wrapper
        );
        List<ManagerEntity> records = page.getRecords();

        //查询创建人名称和上级名称
        List<ManagerVo> vos = new ArrayList<>();
        if (MyCollUtil.isNotEmpty(records)) {
            vos = records.stream().map(po -> {
                ManagerVo managerVo = CopyBean.copyBean(po, ManagerVo.class);

                if (!Objects.equals(po.getCreateManagerId(), TOP1)) {
                    managerVo.setCreateManagerName(Optional.ofNullable(this.getById(po.getCreateManagerId()).getRealName()).orElse(""));
                }
                if (!Objects.equals(po.getHigherId(), TOP1)) {
                    managerVo.setHigherName(Optional.ofNullable(this.getById(po.getHigherId()).getRealName()).orElse(""));
                }
                return managerVo;
            }).collect(Collectors.toList());

            IPage<ManagerVo> pageVo = new Page<>();
            pageVo.setTotal(page.getTotal());
            pageVo.setRecords(vos);
            pageVo.setPages(page.getPages());
            pageVo.setSize(page.getSize());
            pageVo.setCurrent(page.getCurrent());

            return new PageUtils(pageVo);
        }

        return null;
    }

    /**
     * @param oldPwd
     * @param newPwd
     * @return void
     * @description 后台管理系统-修改密码
     * @author zhangyiheng
     * @date 2024/9/8 01:24
     */
    @Override
    @Transactional
    public void updatePwd(String oldPwd, String newPwd) {

        if (!Pattern.matches(PWD, newPwd)) {
            throw new BaseException(CommonExceptionEnum.XGSB_GSCW);
        }

        long id = StpUtil.getLoginIdAsLong();

        ManagerEntity manager = this.getById(id);

        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        if (Objects.isNull(manager) || !bCryptPasswordEncoder.matches(oldPwd, manager.getPassword())) {
            throw new BaseException(CommonExceptionEnum.XGSB_YMMCW);
        }

        //加密
        String newPwdEncoder = bCryptPasswordEncoder.encode(newPwd);

        this.update(Wrappers.<ManagerEntity>lambdaUpdate()
                .set(ManagerEntity::getPassword, newPwdEncoder)
                .eq(ManagerEntity::getManagerId, manager.getManagerId()));

    }

    /**
     * @param managerAddVo
     * @return void
     * @description 后台管理系统-人员表新增下级
     * @author zhangyiheng
     * @date 2024/9/12 11:20
     */
    @Override
    @Transactional
    public void saveManager(ManagerAddVo managerAddVo) {
        ManagerEntity manager = StpUtil.getSession().getModel(SaSession.USER, ManagerEntity.class);
        ManagerEntity managerEntity = CopyBean.copyBean(managerAddVo, ManagerEntity.class);

        //判断如果是省级代理，省级只能存在2个代理，一个省级代理只能发展4个市级代理、区县级代理不受限制。
        //如果是直辖市，一个直辖市只能存在4个代理、区县级代理不受限制。
        long count;
        switch (manager.getLevel()) {
            case LEVE_ADMIN: //admin
                if (!StrUtil.equalsAny(managerAddVo.getLevel(), MUNICIPAL, DISTRICT)) {
                    throw new BaseException(CommonExceptionEnum.DLDJCW);
                }

                if (managerAddVo.getLevel().equals(MUNICIPAL)) {//市 4个
                    count = getCount(managerAddVo, manager, MUNICIPAL);
                    if (Objects.equals(count, 4)) {
                        throw new BaseException(CommonExceptionEnum.FZSJDLSLDDSX.getCode(), StrUtil.format(CommonExceptionEnum.FZSJDLSLDDSX_.getMsg(), managerAddVo.getProvince()));
                    }
                }

                break;
            case MUNICIPAL: //市级
                if (!Objects.equals(managerAddVo.getLevel(), DISTRICT)) {
                    throw new BaseException(CommonExceptionEnum.DLDJCW);
                }
                break;
            default:
                throw new BaseException(CommonExceptionEnum.DLDJFPCW_QCS);
        }

        //判断新增下级的账号/手机号是否重复
        if (accountExist(managerAddVo.getAccount())) {
            throw new BaseException(CommonExceptionEnum.ZHMYCZ);
        }
        if (phoneExist(managerAddVo.getPhone())) {
            throw new BaseException(CommonExceptionEnum.SJHYCZ);
        }
        if (emailExist(managerAddVo.getEmail())) {
            throw new BaseException(CommonExceptionEnum.YXYCZ);
        }

        managerEntity.setLevel(managerAddVo.getLevel());
        long id = manager.getManagerId();
        managerEntity.setHigherId(id);
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        managerEntity.setPassword(encoder.encode(managerAddVo.getPassword()));
        //保存下级
        this.save(managerEntity);

//        //新增用户角色中间表
//        List<Long> roleIds = managerAddVo.getRoleIds();
//        if (MyCollUtil.isNotEmpty(roleIds)) {
//            List<ManagerRoleEntity> managerRoleEntities = roleIds.stream()
//                    .map(new Function<Long, ManagerRoleEntity>() {
//                        @Override
//                        public ManagerRoleEntity apply(Long roleId) {
//                            ManagerRoleEntity userRole = new ManagerRoleEntity();
//                            userRole.setRoleId(roleId);
//                            userRole.setManagerId(managerEntity.getManagerId());
//                            return userRole;
//                        }
//                    }).collect(Collectors.toList());
//            managerRoleService.saveBatch(managerRoleEntities);
//        }

        //修改下级人数
        this.update(Wrappers.<ManagerEntity>lambdaUpdate()
                .set(ManagerEntity::getTotalLower, Optional.ofNullable(manager.getTotalLower()).orElse(0) + 1)
                .eq(ManagerEntity::getManagerId, id));

    }

    private long getCount(ManagerAddVo managerAddVo, ManagerEntity manager, String leve) {
        long count;
        count = this.count(Wrappers.<ManagerEntity>lambdaQuery()
                .eq(ManagerEntity::getLevel, leve)
                .eq(ManagerEntity::getCity, managerAddVo.getCity())
                .eq(ManagerEntity::getHigherId, manager.getManagerId()));
        return count;
    }


    //校验邮箱是否重复
    private boolean emailExist(String email) {
        if (StrUtil.isNotBlank(email)) {
            long count = this.count(Wrappers.<ManagerEntity>lambdaQuery()
                    .eq(ManagerEntity::getEmail, email));
            return count > 0L;
        }
        return false;
    }

    //校验手机号是否重复
    private boolean phoneExist(String phone) {
        long count = this.count(Wrappers.<ManagerEntity>lambdaQuery()
                .eq(ManagerEntity::getPhone, phone));
        return count > 0L;
    }

    //校验账号是否重复
    private boolean accountExist(String account) {
        long count = this.count(Wrappers.<ManagerEntity>lambdaQuery()
                .eq(ManagerEntity::getAccount, account));
        return count > 0L;
    }

    /**
     * @param managerId
     * @return void
     * @description 后台管理系统-修改状态
     * @author zhangyiheng
     * @date 2024/9/12 12:34
     */
    @Override
    @Transactional
    public void updateStatus(Long managerId) {
        //确定上下级关系
        ManagerEntity managerEntity = determineTheSubordinateRelationship(managerId);

        //查询下级是否存在下级
        hasNext(managerId, managerEntity);

        //修改状态
        String status = "";
        switch (managerEntity.getStatus()) {
            case STOP:
                status = OPEN;
                break;
            case OPEN:
                status = STOP;
                break;
            default:
                break;
        }
        this.update(Wrappers.<ManagerEntity>lambdaUpdate()
                .set(ManagerEntity::getStatus, status)
                .eq(ManagerEntity::getManagerId, managerId));

        //下线
        StpUtil.kickout(managerId);
    }


    /**
     * @param managerId
     * @return com.yufubao.model.pojo.management.authorization.ManagerEntity
     * @description 确定上下级关系
     * @author zhangyiheng
     * @date 2024/9/12 13:52
     */
    private ManagerEntity determineTheSubordinateRelationship(Long managerId) {
        ManagerEntity entity = this.getById(managerId);

        ManagerEntity manager = StpUtil.getSession().getModel(SaSession.USER, ManagerEntity.class);
        //确定上下级关系
        if (!Objects.equals(manager.getManagerId(), entity.getHigherId())) {
            throw new BaseException(CommonExceptionEnum.NOT_PERMISSION);
        }
        return entity;
    }


    /**
     * @param managerId
     * @param managerEntity
     * @return void
     * @description 查询下级是否存在下级
     * @author zhangyiheng
     * @date 2024/9/12 13:52
     */
    private void hasNext(Long managerId, ManagerEntity managerEntity) {
        //查询下级是否存在下级
        if (!Objects.equals(managerEntity.getLevel(), DISTRICT)) {
            long count = this.count(Wrappers.<ManagerEntity>lambdaQuery()
                    .eq(ManagerEntity::getHigherId, managerId));
            if (count > 0) {
                throw new BaseException(CommonExceptionEnum.SCSB_XX_CZQTXJCY.getCode(), StrUtil.format(CommonExceptionEnum.SCSB_XX_CZQTXJCY.getMsg(), managerEntity.getRealName()));
            }
        }
    }

    /**
     * @param managerIds
     * @return void
     * @description 删除下级
     * @author zhangyiheng
     * @date 2024/9/12 12:41
     */
    @Override
    @Transactional
    public void remove(Long[] managerIds) {
        for (Long managerId : managerIds) {
            //确定上下级关系
            ManagerEntity managerEntity = determineTheSubordinateRelationship(managerId);

            //判断状态
            if (Objects.equals(managerEntity.getStatus(), OPEN)) {
                throw new BaseException(CommonExceptionEnum.SCSB_CZZZQYDXJ);
            }

            //查询下级是否存在下级
            hasNext(managerId, managerEntity);

        }
        //删除下级
        this.removeByIds(Arrays.asList(managerIds));

        //修改下级数量
        ManagerEntity manager = StpUtil.getSession().getModel(SaSession.USER, ManagerEntity.class);
        this.update(Wrappers.<ManagerEntity>lambdaUpdate()
                .set(ManagerEntity::getTotalLower, Optional.ofNullable

                        (manager.getTotalLower()).orElse(0) - managerIds.length)
                .eq(ManagerEntity::getManagerId, manager.getManagerId()));

        //注销
        for (Long managerId : managerIds) {
            StpUtil.logout(managerId);
        }
    }

    /**
     * @param managerId
     * @return com.yufubao.model.vo.management.sys.UpdateManagerRoleVO
     * @description 回显修改下级角色的角色信息
     * @author zhangyiheng
     * @date 2024/9/12 22:34
     */
    @Override
    public UpdateManagerRoleVO updateRoleEcho(Long managerId) {
        //查出用户所关联的角色id
        List<ManagerRoleEntity> managerRoleEntities = managerRoleService.list(Wrappers.<ManagerRoleEntity>lambdaQuery()
                .eq(ManagerRoleEntity::getManagerId, managerId));
        List<Long> roleIds = managerRoleEntities.stream()
                .map(ManagerRoleEntity::getRoleId).collect(Collectors.toList());

        //查出所有角色属性
        List<RoleEntity> roles = roleService.list();
        List<SelectRoleVO> roleVo = CopyBean.copyBeanList(roles, SelectRoleVO.class);
        //封装信息
        UpdateManagerRoleVO updateUserRoleVO = new UpdateManagerRoleVO();
        updateUserRoleVO.setRoleIds(roleIds);
        updateUserRoleVO.setRoles(roleVo);

        return updateUserRoleVO;
    }

    /**
     * @param roleIds
     * @param managerId
     * @return void
     * @description 更新下级角色信息
     * @author zhangyiheng
     * @date 2024/9/12 22:41
     */
    @Override
    @Transactional
    public void updateRole(List<Long> roleIds, Long managerId) {
        //先删除用户对应角色的id数据
        if (!roleIds.isEmpty()) {
            managerRoleService.remove(Wrappers.<ManagerRoleEntity>lambdaQuery()
                    .eq(ManagerRoleEntity::getManagerId, managerId));
        }

        //插入用户角色数据
        try {
            List<ManagerRoleEntity> userRoles = roleIds.stream()
                    .map(new Function<Long, ManagerRoleEntity>() {
                        @Override
                        public ManagerRoleEntity apply(Long roleId) {
                            ManagerRoleEntity managerRoleEntity = new ManagerRoleEntity();
                            managerRoleEntity.setManagerId(managerId);
                            managerRoleEntity.setRoleId(roleId);
                            return managerRoleEntity;
                        }
                    }).collect(Collectors.toList());
            managerRoleService.saveBatch(userRoles);
            //下线
            StpUtil.logout(managerId);
        } catch (Exception e) {
            log.info("用户角色数据修改失败 {} ", e);
        }
    }


    //    /**
//     * @return com.yufubao.framework.result.PageUtils
//     * @description 后台管理系统-查询各级别人员信息
//     * @author zhangyiheng
//     * @date 2024/9/12 09:44
//     */
//    @Override
//    public PageUtils getAllLeveManager() {
//        long managerId = StpUtil.getLoginIdAsLong();
//        LeveManagerVo leveManagerVo = new LeveManagerVo();
//        //admin查询所有
//        if (Objects.equals(managerId, ADMIN)) {
//            List<ManagerEntity> allList = this.list();
//            if (MyCollUtil.isNotEmpty(allList)) {
//                //市级
//                leveManagerVo.setMunicipal(getLeve(allList, MUNICIPAL));
//
//                //省级
//                leveManagerVo.setProvincial(getLeve(allList, PROVINCIAL));
//
//                //区/县
//                leveManagerVo.setDistrict(getLeve(allList, DISTRICT));
//            }
//        }else {
//            //查询当前人员的下级信息
//            List<ManagerEntity> list = this.list(Wrappers.<ManagerEntity>lambdaQuery()
//                    .eq(ManagerEntity::getHigherId, managerId));
//
//        }
//        return null;
//    }
//
//
//    private List<ManagerNameCategoryVo> getLeve(List<ManagerEntity> allList, String leve) {
//        if (MyCollUtil.isNotEmpty(allList)) {
//            return allList.stream().map(
//                    po -> {
//                        if (po.getLevel().equals(leve)) {
//                            ManagerNameCategoryVo vo = new ManagerNameCategoryVo();
//                            vo.setManagerId(po.getManagerId());
//                            vo.setLevel(po.getLevel());
//                            vo.setRealName(po.getRealName());
//                            vo.setRegion(po.getCity() + po.getProvince() + po.getCounty());
//                            allList.remove(po);
//                            return vo;
//                        }
//                        return null;
//                    }).collect(Collectors.toList());
//        }
//        return null;
//    }
}